package com.neolix.watch;

import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.util.Log;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.neolix.watch.bluetooth.BluetoothLeService;
import com.neolix.watch.domain.WeatherLocation;
import com.neolix.watch.service.AlarmManagerBroadcastReceiver;
import com.neolix.watch.service.BackgroundTaskService;
import com.neolix.watch.util.Constant;
import com.neolix.watch.weather.GetWeatherTask;
import com.neolix.watch.weather.UpdateLocationTask;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;

import org.acra.ACRA;
import org.acra.ReportField;
import org.acra.ReportingInteractionMode;
import org.acra.annotation.ReportsCrashes;

import static android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE;
import static com.neolix.watch.util.SharedPreferencesUtil.saveLocation;

@ReportsCrashes(formKey = "", // will not be used
        mailTo = "neolix@163.com",
        customReportContent = {
                ReportField.APP_VERSION_CODE,
                ReportField.APP_VERSION_NAME,
                ReportField.ANDROID_VERSION,
                ReportField.PHONE_MODEL,
                ReportField.DISPLAY,
                ReportField.SHARED_PREFERENCES,
                ReportField.CUSTOM_DATA,
                ReportField.STACK_TRACE,
                ReportField.LOGCAT},
        mode = ReportingInteractionMode.TOAST,
        sendReportsInDevMode = true,
        resToastText = R.string.crash_text)
public class NeolixApplication extends Application {
    private static NeolixApplication application;
    public LocationClient locationClient;
    public BluetoothLeService bluetoothLeService;

    public static NeolixApplication getInstance() {
        return application;
    }

    @Override
    public void onCreate() {
        Log.i(Constant.BLUETOOTH_TAG, "createApp");
        application = this;
        ACRA.init(this);
        if (!couldDebug()) {
            ACRA.getErrorReporter().setReportSender(new ACRAReportSender(this));
        }

        super.onCreate();
    }

    public void initApp() {
        Log.i(Constant.BLUETOOTH_TAG, "initApp");
        initImageLoader(getApplicationContext());
        initLocation();

        bindBluetoothService();
    }

    public void initLocation() {
        locationClient = new LocationClient(this);
        locationClient.registerLocationListener(new MyLocationListener());
    }

    private void bindBluetoothService() {
        Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
        bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
        Log.i(Constant.BLUETOOTH_TAG, "bindService");
    }

    private boolean couldDebug() {
        PackageManager pm = getPackageManager();
        try {
            int flags = pm.getApplicationInfo(getPackageName(), 0).flags;
            return ((flags & FLAG_DEBUGGABLE) > 0);
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        }
    }

    public static void initImageLoader(Context context) {
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
                .threadPriority(Thread.NORM_PRIORITY - 2)
                .denyCacheImageMultipleSizesInMemory()
                .discCacheFileNameGenerator(new Md5FileNameGenerator())
                .tasksProcessingOrder(QueueProcessingType.LIFO)
                .writeDebugLogs()
                .build();
        ImageLoader.getInstance().init(config);
    }

    private class MyLocationListener implements BDLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {
            //Receive Location
            WeatherLocation weatherLocation = new WeatherLocation();
            StringBuilder sb = new StringBuilder(256);
            sb.append("time : ");
            sb.append(location.getTime());
            sb.append("\nerror code : ");
            sb.append(location.getLocType());
            sb.append("\nlatitude : ");
            weatherLocation.setLatitude(location.getLatitude());
            sb.append(location.getLatitude());
            sb.append("\nlontitude : ");
            weatherLocation.setLontitude(location.getLongitude());
            sb.append(location.getLongitude());
            sb.append("\nradius : ");
            sb.append(location.getRadius());
            if (location.getLocType() == BDLocation.TypeGpsLocation) {
                sb.append("\nspeed : ");
                sb.append(location.getSpeed());
                sb.append("\nsatellite : ");
                sb.append(location.getSatelliteNumber());
                sb.append("\ndirection : ");
                sb.append(location.getDirection());
            } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
                sb.append("\naddr : ");
                weatherLocation.setAddress(location.getAddrStr());
                sb.append(location.getAddrStr());
                sb.append("\noperationers : ");
                sb.append(location.getOperators());
            }
            Log.i("BaiduLocationApiDem", sb.toString());

            saveLocation(weatherLocation);

            Intent intent = new Intent();
            intent.setAction(Constant.COM_NEOLIX_WATCH_LOCATION_CHANGE);
            sendBroadcast(intent);
            BackgroundTaskService.submitTask(getApplicationContext(), GetWeatherTask.class);
        }

        @Override
        public void onReceivePoi(BDLocation arg0) {

        }
    }

    private final ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            bluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
            if (!bluetoothLeService.initialize()) {
                Log.i(Constant.BLUETOOTH_TAG, "initialize Bluetooth failure");
            } else {
                Log.i(Constant.BLUETOOTH_TAG, "initialize Bluetooth successful");
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.i(Constant.BLUETOOTH_TAG, "onServiceDisconnected");
            bluetoothLeService = null;
//            bindBluetoothService();
        }
    };

    public boolean isConnectWatch() {
        if (getInstance().bluetoothLeService == null)
            return false;
        return getInstance().bluetoothLeService.getConnectionState() == BluetoothLeService.STATE_CONNECTED;
    }

    public void exitApp() {
        Log.i(Constant.BLUETOOTH_TAG, "exitApp");
        locationClient.stop();
        AlarmManagerBroadcastReceiver.cancelAlarm(getApplicationContext());
        unbindService(mServiceConnection);
    }
}
